#pragma once
#include <string>
#include <string_view>
#include <type_traits>

#include <cstdio>

#include "class_name.h"

namespace rft
{
	class object {
	public:
		virtual ~object();
		virtual std::size_t hash_code() const;
		virtual std::string to_string() const;
		virtual std::string_view get_class_name() const;

	public:
		template <typename T, typename E = std::enable_if_t<!std::is_compound_v<std::decay_t<T>>>>
		static std::string_view get_class_name(T&& obj) {
			return get_static_name<T>();
		}

		template <typename T, typename E = std::enable_if_t<!std::is_compound_v<std::decay_t<T>>>>
		static std::string to_string(T&& obj) { return std::to_string(std::forward<T&&>(obj)); }

		template <typename T, typename std::enable_if_t<std::is_convertible_v<std::decay_t<T>, object>, int> = 0>
		static std::string_view get_class_name(T&& obj) {
			return (std::forward<T&&>(obj)).get_class_name();
		}

		template <typename T, typename std::enable_if_t<std::is_convertible_v<std::decay_t<T>, object>, int> = 0>
		static std::string_view get_class_name(T* obj) {
			return obj->get_class_name();
		}
	};

	class parseable {
	public:
		virtual ~parseable();
		virtual object* parse(std::string_view) = 0;
	};
}